﻿
Imports System.Threading
Imports std
Imports storoomc
Imports wfileis.data

Public Module wfindex
    Public Const indexSleepTimeMS As Int64 = 14400 * 1000 'every four hours
    Public Const defaultConfigfile As String = "wfindex.ini"
    Public WithEvents config As configMonitor = Nothing
    Public fulllist As [set](Of String) = Nothing
    Public sourcetalk As storoomTalk = Nothing
    Public desttalk As storoomTalk = Nothing
    Public tp As threadpool = Nothing

    Private indexthread As Thread = Nothing

    Public Enum keytype
        info
        category
        record
        unknown             'contains all index & maybe something i missed
    End Enum

    Public Function checkkeytype(ByVal key As String, _
                                 Optional ByRef keyprefix As String = Nothing, _
                                 Optional ByRef storekey As String = Nothing) As keytype
        storehelper.breakupkey(key, keyprefix, storekey)
        If strsame(keyprefix, info._keyprefix, True) Then
            Return keytype.info
        ElseIf strsame(keyprefix, category._keyprefix, True) Then
            Return keytype.category
        ElseIf strsame(keyprefix, record._keyprefix, True) Then
            Return keytype.record
        ElseIf isdebugmode() Then
            'log the no-match key for debug only
            raiseError("key " + key + " does not match, prefix " + keyprefix + ", storekey " + storekey)
        End If

        Return keytype.unknown
    End Function

    Private Delegate Sub indexDelegate()

    Private Sub indexImpl(ByVal i As indexDelegate)
        assert(Not i Is Nothing, "indexDelegate is nothing.")
        Try
            i()
        Catch ex As Exception
            raiseError("caught unexpected exception, ex " + ex.Message + ", call stack " + ex.StackTrace(), _
                       errorHandle.errorType.critical)
        End Try
    End Sub

    Private Sub index()
        While True
            If Not sourcetalk.list(fulllist) Then
                raiseError("cannot read full list from source storoom, wait for next round.", _
                           errorHandle.errorType.warning)
            Else
                indexImpl(AddressOf alllist.index)
                indexImpl(AddressOf timeline.index)
            End If
            raiseError("finish a round of index, wait for next round.")
            sleep(indexSleepTimeMS)
        End While
    End Sub

    Private Sub initialtalk(ByRef talk As storoomTalk, ByVal host As String, ByVal port As Int32)
        If talk Is Nothing Then
            talk = New storoomTalk(host, port)
        Else
            talk.initial(host, port)
        End If
        talk.liveTime = (indexSleepTimeMS << 1)
    End Sub

    Private Sub startService()
        Dim host As String = Nothing
        Dim port As Int32
        If Not parseHostPort(config.parameter(configNaming.wfindex.name, configNaming.wfindex.sourceaddress, _
                                              configNaming.defaultValue.wfindex.sourceaddress), _
                             host, port) Then
            raiseError("cannot read source host & port from configuration.", errorHandle.errorType.exclamation)
            Exit Sub
        Else
            initialtalk(sourcetalk, host, port)
        End If
        If Not parseHostPort(config.parameter(configNaming.wfindex.name, configNaming.wfindex.destaddress, _
                                              configNaming.defaultValue.wfindex.destaddress), _
                             host, port) Then
            raiseError("cannot read dest host & port from configuration.", errorHandle.errorType.exclamation)
            Exit Sub
        Else
            initialtalk(desttalk, host, port)
        End If
        tp = New threadpool(2)
        indexthread = startThread(AddressOf index)
    End Sub

    Private Sub shutdown()
        If Not indexthread Is Nothing Then
            indexthread.Abort()
        End If
        tp.stop()
    End Sub

    Private Sub monitor()
        While Not consoleCancelKeyPressed() AndAlso Not indexthread Is Nothing AndAlso indexthread.IsAlive()
            sleep()
        End While
    End Sub

    Private Sub unhandledException(ByVal ex As Exception)
        shutdown()
    End Sub

    Public Sub main(ByVal args() As String)
        startmain(AddressOf unhandledException)
        Dim configfile As String = Nothing
        If args.Length() > 0 Then
            configfile = args(0)
        Else
            configfile = defaultConfigfile
        End If
        config = New configMonitor()
        assert(config.open(configfile), "cannot open configuration file " + configfile)
        startService()
        monitor()
        shutdown()
        finishmain()
    End Sub

    Private Sub config_ConfigChanged() Handles config.ConfigChanged
        shutdown()
        startService()
    End Sub

    Private Sub config_ConfigfileDeleted() Handles config.ConfigfileDeleted
        If configMonitor.defaultConfigDeletedOperation(60 * 60 * 2, 1024) Then
            shutdown()
        End If
    End Sub
End Module

Namespace configNaming
    Namespace wfindex
        Public Module wfindex
            Public Const name As String = "wfindex"
            Public Const sourceaddress As String = "sourceaddress"
            Public Const destaddress As String = "destaddress"
        End Module
    End Namespace

    Namespace defaultValue
        Namespace wfindex
            Public Module wfindex
                Public Const sourceaddress As String = "hzj-jie-8320-1:42402"
                Public Const destaddress As String = "hzj-jie-8320-1:42402"
            End Module
        End Namespace
    End Namespace
End Namespace
